package top.atcra.rpc.transport.response;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import lombok.extern.slf4j.Slf4j;
import top.atcra.rpc.RPCBootstrap;
import top.atcra.rpc.compress.Compressor;
import top.atcra.rpc.compress.CompressorFactory;
import top.atcra.rpc.serialization.Serializer;
import top.atcra.rpc.serialization.SerializerFactory;
import top.atcra.rpc.transport.message.RPCResponse;
import top.atcra.rpc.transport.utils.MessageFormatConstant;

/**
 * 响应编码器
 *
 * @author atcra
 * @date 2025-3-23
 */
@Slf4j
public class RPCResponseEncoder extends MessageToByteEncoder<RPCResponse> {
    @Override
    protected void encode(ChannelHandlerContext ctx, RPCResponse msg, ByteBuf out) throws Exception {
        out.writeBytes(MessageFormatConstant.PROTOCOL_ID);
        out.writeByte(MessageFormatConstant.VERSION);
        out.writeShort(MessageFormatConstant.HEADER_LENGTH);
        // 现阶段跳过响应长度
        out.writerIndex(out.writerIndex() + MessageFormatConstant.FULL_FIELD_LENGTH);
        out.writeByte(msg.getSerializeType());
        out.writeByte(msg.getCompressType());
        out.writeLong(msg.getRequestId());
        out.writeLong(msg.getTimestamp());
        out.writeByte(msg.getCode());

        byte[] body = null;
        if (msg.getBody() != null) {
            Serializer serializer = SerializerFactory.getSerializer(msg.getSerializeType());
            body = serializer.serialize(msg.getBody());
            Compressor compressor = CompressorFactory.getCompressor(msg.getCompressType());
            body = compressor.compress(body);
            out.writeBytes(body);
        }

        // 重新处理报文的总长度
        // 先保存当前写指针的位置
        int bufTail = out.writerIndex();
        // 将写指针移动到 总长度字段 所在位置
        out.writerIndex(MessageFormatConstant.PROTOCOL_ID.length + MessageFormatConstant.VERSION_FILED_LENGTH + MessageFormatConstant.HEADER_FIELD_LENGTH);

        // 将总长度写入
        out.writeInt(MessageFormatConstant.HEADER_LENGTH + (body == null ? 0 : body.length));

        // 恢复写指针
        out.writerIndex(bufTail);


        if (log.isDebugEnabled()) {
            log.debug("编号为{}的响应已经完成报文的编码", msg.getRequestId());
        }
        RPCBootstrap.qpsCountIncrease();

    }
}
